<template>
  <div class="yy-widget-form">
    <el-form
        ref="formWidgetRef"
        :style="option.style"
        :model="formData"
        :rules="rules"
        :label-width="option.formLabelWidth || 'auto'"
        status-icon
    >
      <template v-for="field in props.formFields" :key="field.field">
        <el-form-item v-if="(typeof field.hide === 'function' ? !field.hide() : !field.hide) && field.type != 'template'" :label="field.label" :prop="field.field" :style="option.itemStyle">
          <AvatarSelector v-if="field.type === 'avatar'" :init-value="formData[field.field]" @success="onUploadAvatar($event, field)"/>
          <el-input v-if="field.type === 'text'"
                    :style="field.style"
                    :placeholder="field.placeholder"
                    :clearable="field.config?.input.clearable"
                    v-model="formData[field.field]"
                    :disabled="typeOf(field.readonly) === 'function' ? field.readonly(formData) : field.readonly"
                    @change="onFormFieldChange(field)"
          />
          <el-select ref="widgetFormSelectRef" :field-name="field.field" v-if="field.type === 'select'"
                     :placeholder="field.placeholder"
                     automatic-dropdown
                     :style="field.style"
                     :disabled="typeOf(field.readonly) === 'function' ? field.readonly(formData) : field.readonly"
                     :clearable="!!field.config?.select?.clearable"
                     :filterable="!!field.config?.select?.filterable"
                     :remote="!!field.config?.select?.remote"
                     :reserve-keyword="!!field.config?.select?.reserveKeyword"
                     :remote-show-suffix="!!field.config?.select?.remoteShowSuffix"
                     :remote-method="field.config?.select?.remoteMethod"
                     :multiple="field.config?.select?.multiple"
                     v-model="formData[field.field]"
                     @change="onSelectChange(field.field, field)"
          >
            <el-option
                v-for="item in field.options"
                :key="item.key || item.value"
                :label="item.label"
                :value="item.value"
            />
          </el-select>
          <el-input-number v-if="field.type === 'number'" :min="0" :placeholder="field.placeholder" v-model="formData[field.field]" @change="onFormFieldChange(field)"/>
          <el-input v-if="field.type === 'textarea'" type="textarea" :rows="2" :placeholder="field.placeholder" v-model="formData[field.field]" @change="onFormFieldChange(field)"/>
          <el-radio-group v-if="field.type === 'radioGroup'" v-model="formData[field.field]" @change="onFormFieldChange(field)">
            <template :key="item.value"  v-for="item in field.options">
              <el-radio :value="item.value">{{ item.label}}</el-radio>
            </template>
          </el-radio-group>
          <el-checkbox-group
              v-if="field.type === 'checkboxGroup'"
              v-model="formData[field.field]"
              @change="onFormFieldChange(field)"
          >
            <el-checkbox  :key="item.value"  v-for="item in field.options" :label="item.value">{{item.label }}</el-checkbox>
          </el-checkbox-group>
          <el-date-picker v-if="field.type === 'date'" v-model="formData[field.field]" type="date" :placeholder="field.placeholder" @change="onFormFieldChange(field)"/>
          <el-date-picker v-if="field.type === 'datetime'" v-model="formData[field.field]" type="datetime" :placeholder="field.placeholder" @change="onFormFieldChange(field)"/>
          <el-date-picker
              v-if="field.type==='dateRange'"
              v-model="formData[field.field]"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              @change="onFormFieldChange(field)"
          />
          <component v-if="field.type === 'templateField'" :is="field.component" :field="field" :option="option" v-model="formData[field.field]" :placeholder="field.placeholder" :style="field.style"
            @change="field.atChange"
          />
        </el-form-item>

        <component ref="componentFormRef" v-else-if="(typeof field.hide === 'function' ? !field.hide() : !field.hide) && field.type === 'template'" :is="field.component" :field="field" :option="option"/>
      </template>
      <el-form-item v-if="formButtons?.length" :style="option.itemStyle">
        <div class="yy-widget-form_btn">
          <el-button v-for="(button, index) in formButtons" :key="index"  :icon="button.icon" :type="button.type || 'primary'" @click.stop="onFormButtonClick(button)"> {{ button.label }}</el-button>
        </div>
      </el-form-item>
    </el-form>
  </div>
</template>
<script setup lang="ts">
import {defineEmits, defineExpose, defineProps, nextTick, onMounted, provide, reactive, ref, watch} from 'vue'
import {FormInstance, FormRules} from "element-plus";
import {WidgetFormField} from "../../model/Definition";
import {FormItemRule} from "element-plus/es/components/form/src/types";
import {BaseModel} from "@/model/BaseModel";
import {typeOf} from "@/utils/yayi";
import AvatarSelector from "@/components/widget/AvatarSelector.vue";

const props = defineProps({
  option: {
    type: Object,
    required: false,
    default: () => Object.assign({
      size: '30%'
    })
  },
  formFields: {
    type: Object,
    required: true,
    default: () => []
  },
  formButtons: {
    type: Array,
    required: false,
    default: null
  }
})

const isLoading = ref(false)
const formWidgetRef = ref<FormInstance>()
const widgetFormSelectRef = ref()
const componentFormRef = ref([])

const formData = ref({})

// 当前form表单验证规则
const rules = reactive<FormRules>({})

const $emit = defineEmits({
  editCallback: ((data: BaseModel) => data),
})

const onUploadAvatar = (url, formField: WidgetFormField) => {
  formData.value[formField.field] = url
}

const onSelectChange = (field: string, formField: WidgetFormField) => {
  for(let selectRef of widgetFormSelectRef.value) {
    if (!formField.config?.select?.multiple && selectRef.$attrs['field-name'] === field) {
      selectRef.blur()
    }
  }
  if (typeOf(formField.atChange) === 'function') {
    formField.atChange(formData.value[field], formField)
  }
}

const onFormFieldChange = (formField: WidgetFormField) => {
  if (typeOf(formField.atChange) === 'function') {
    formField.atChange(formData.value[formField.field], formField)
  }
}

const onFormButtonClick = (button) => {
  if (button.atClick) {
    button.atClick(button)
  }
}

const initForm = () => {
  const obj = {}
  props.formFields.forEach((fieldObj: WidgetFormField) => {
    obj[fieldObj.field] = typeOf(fieldObj.initVal) == 'function' ? fieldObj.initVal() : fieldObj.initVal
    if (fieldObj.required?.length) {
      const ruleItems:FormItemRule[] = []
      fieldObj.required.forEach(item => {
        ruleItems.push({
          required: item.required,
          message: item.message,
          validator: item.validator || undefined,
          trigger: item.trigger || undefined
        })
      })
      rules[fieldObj.field] = ruleItems
    }
  })
  console.log('init form val:::', obj)
  formData.value = obj
}

const showOrHideField = (field: string, isHide: boolean) => {
  if (componentFormRef.value?.length) {
    componentFormRef.value.forEach((instance) => {
      instance.showOrHideField(field, isHide)
    })
  }
}

const initFormData = (data) => {
  if (props.formFields?.length) {
    const obj = {}
    props.formFields.forEach((fieldObj: WidgetFormField) => {
      obj[fieldObj.field] = data ? data[fieldObj.field] : typeOf(fieldObj.initVal) == 'function' ? fieldObj.initVal() : fieldObj.initVal
    })
    if (componentFormRef.value?.length) {
      componentFormRef.value.forEach((instance) => {
        instance.initFormData(data)

      })
    }
    console.log('----init form data------', obj)
    nextTick(() => {
      formData.value = obj
    })
  }
}

const setFieldValue = (field: string, val: any) => {
  for (let key in formData.value) {
    if (key === field) {
      formData.value[key] = val
    }
  }
}

const resetFields = () => {
  formWidgetRef.value.resetFields()
  if (componentFormRef.value?.length) {
    componentFormRef.value.forEach((instance) => {
      instance.resetFields()
    })
  }
  formData.value = {}
}

const validateForm = (callback) => {
  formWidgetRef.value.validate((valid, fields) => {
    console.log('widget form validate:::', valid, fields)
    callback && callback(valid, fields)
  })
}

const getFormFieldValue = () => {
  let modelProperty = {}
  for (let key in formData.value) {
    const formField = props.formFields.find(ff => ff.field === key)
    if (formField.formatValFun && typeOf(formField.formatValFun) === 'function') {
      modelProperty[key] = formField.formatValFun(formData.value[key], formField)
    } else {
      modelProperty[key] = formData.value[key]
    }

  }

  if (componentFormRef.value?.length) {
    componentFormRef.value.forEach((instance) => {
      modelProperty = Object.assign({}, modelProperty, instance.getFormFieldValue())
    })
  }
  return modelProperty
}

watch(() => props.formFields, () => {
  if (props.formFields?.length) {
    initForm()
  }
}, {immediate: true})

defineExpose({
  initForm,
  initFormData,
  resetFields,
  validateForm,
  getFormFieldValue,
  setFieldValue,
  showOrHideField,
})

</script>
<style scoped lang="scss">
.yy-widget-form {
  &_btn {
    display: flex;
    flex-direction: row;
    width: 100%;
    & > button {
      flex: 1;
    }
  }
}
</style>